package cn.im.tool;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.io.UnsupportedEncodingException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Base64;
import java.util.Date;

/**
 * jwt工具类   分布式跨域身份验证解决方案
 * jwt组成: base64(header).base64(payload).HS256(signature)
 * header: 指明令牌类型和加密算法 {"alg": "HS256","typ": "JWT"}
 * payload: 存储服务器需要的数据 {"user": "xxx","role":"xxx"}   withClaim()方法,不要存放敏感信息
 *signature: 使用HMACSHA256算法计算  HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),Secret)
 *
 */
public class JwtTool {

    /**
     * 密钥
     */
    private static final String SECRET = "sdAfi245l";

    /**
     * token生成
     * 可自定义参数规范
     * @param user  用户名
     * @param role  角色
     * @param expireTime 过期时间  单位:min
     * @return  token
     */
    public static String create(String user,String role,long expireTime){
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            /**
             * iss (issuer)：签发人
             * exp (expiration time)：过期时间
             * sub (subject)：主题
             * aud (audience)：受众
             * nbf (Not Before)：生效时间
             * iat (Issued At)：签发时间
             * jti (JWT ID)：编号
             */
            String token = JWT.create().withIssuer("autho0")
                    .withSubject("subject")
                    .withExpiresAt(Date.from(LocalDateTime.now().plusMinutes(expireTime).atZone(ZoneId.systemDefault()).toInstant()))
                    .withClaim("user",user)
                    .withClaim("role",role)
                    .sign(algorithm);
            return token;
        } catch (JWTCreationException e) {
            //Invalid Signing configuration / Couldn't convert Claims
            e.printStackTrace();
            throw e;
        }
    }


    /**
     * token校验
     * @param token
     * @return
     */
    public static Boolean verify(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256(SECRET);
            JWTVerifier verifier = JWT.require(algorithm).withIssuer("autho0").build();
            DecodedJWT jwt = verifier.verify(token);
            Date expiresAt = jwt.getExpiresAt();
//            System.out.println(expiresAt);
//            String payload = jwt.getPayload();
//            String id = jwt.getClaim("id").asString();
//            String value = jwt.getClaim("value").asString();
//            System.out.println("payload: "+payload);
//            System.out.println("id: "+id);
//            System.out.println("value: "+value);
            return true;
        }catch (JWTVerificationException e) {
            //Invalid signature/claims
            return false;
        }
    }

    public static void main(String[] args) throws UnsupportedEncodingException {
        String token = create("sessionid","xx.xx",1);
        System.out.println("token: " + token);
        Boolean result = verify(token);
        System.out.println(result);
        System.out.println();



        /**
         * jwt解密
         */
        String tempToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiYXV0aG8wIiwiaWQiOiJzZXNzaW9uaWQiLCJleHAiOjE2MTI2NjYxNDcsInZhbHVlIjoieHgueHgifQ.NslrGdX2RT_RaLSCmzEk_wOCrdZDqflRqbcWHaUSo3Y";
        String header = new String(Base64.getDecoder().decode(tempToken.substring(0,tempToken.indexOf("."))));
        System.out.println("header: "+header);
        String decodePayload = new String(Base64.getDecoder().decode(tempToken.substring(tempToken.indexOf(".")+1,tempToken.lastIndexOf(".")).getBytes("UTF-8")));
        System.out.println("Payload: "+decodePayload);
        System.out.println(verify(tempToken));
    }
}
